GO
1. 算术运算符
常见的Shell算术运算符见下表:
算术运算符 | 意义(*表示常用) |
---|---|
+ 、- |
加法(或正号)、减法(或负号)* |
* 、/ 、% |
乘法、除法、取余(取模)* |
** |
幂运算* |
++ 、-- |
增加及减少,可前置也可放在变量结尾* |
! 、&& 、双竖 |
逻辑非(取反)、逻辑与(and)、逻辑或(or)* |
< 、<= 、> 、>= |
比较符号(小于、小于等于、大于、大于等于) |
== 、!= 、= |
比较符号(相等、不相等,对于字符串= 也可以表示相当于)* |
<< 、>> |
向左移位、向右移位 |
~ 、单竖 、& 、^ |
按位取反、按位异或、按位与、按位或 |
= 、+= 、-= 、*= 、/= 、%= |
赋值运算,例如a+=1 相当于a=a+1 ,a-=1 相当于a=a-1 * |
上表中的算术运算符号均适用于常见的运算命令。常见的运算命令见下表:
运算操作符与运算命令 | 意义 |
---|---|
(()) |
用于整数运算的常用运算符,效率很高 |
let |
用于整数运算,类似于(()) |
expr |
可用于整数运算,但还有很多其他的额外功能 |
bc |
Linux下的一个计算器程序(适合整数及小数运算) |
$[] |
用于整数运算 |
awk |
awk 既可以用于整数运算,也可以用于小数运算 |
declare |
定义变量值和属性,-i 参数可以用于定义整型变量,做运算 |
下面的内容,将逐一讲解Shell中的各种运算符号及运算命令。
2. 双小括号 (()) 数值运算的基础语
2.1. 双小括号 (()) 数值运算的基础语法
双小括号(())
的作用是进行数值运算与数值比较,它的效率很高,用法灵活,是企业场景运维人员经常采用的运算操作符,其操作方法见下表:
运算操作符与运算命令 | 意义 |
---|---|
((i=i+1)) |
此种书写方法为运算后赋值法,即将i+1 的运算结果赋值给变量i 。注意,不能用echo ((i=i+)) 的形式输出表达式的值,但可以用echo $((i=i+1)) 输出其值 |
i=$((i+1)) |
可以在(()) 前加$ 符,表示将表达式运算后赋值给i |
((8>7&&5==5)) |
可以进行比较操作,还可以加入逻辑与和逻辑或,用于条件判断 |
echo $((2+1)) |
需要直接输出运算表达式的运算结果时,可以在(()) 前加$ 符 |
2.2. 双小括号 (()) 数值运算实践
例1:利用
(())
进行简单的数值计算12345678[root@theshu ~]2[root@theshu ~]3[root@theshu ~][root@theshu ~][root@theshu ~]10例2:利用
(())
进行稍微复杂一些的综合算术运算12345678910111213[root@theshu ~]# ((a=1+2**3-4%3)) #<==这是一个较复杂的表达式运算并赋值的操作,其中2**3表示2的三次方[root@theshu ~]# echo $a8 #<==表达式运算后将结果赋值给a ,先乘除后加减[root@theshu ~]# b=$((1+2**3-4%3)) #<==这是另一种表达式运算后将结果赋值给变量的写法,变量放在了括号的外面[root@theshu ~]# echo $b8[root@theshu ~]# echo $((1+2**3-4%3)) #<==还可以直接运算表达式并将结果输出,注意,不要落下$符号8[root@theshu ~]# a=$((100*(100+1)/2)) #<==利用公式计算1到100的和[root@theshu ~]# echo $a5050[root@theshu ~]# echo $((100*(100+1)/2)) #<==直接输出表达式的结果5050例3:特殊运算符号的运算小示例
1234567[root@theshu ~]# a=8[root@theshu ~]# echo $((a=a+1)) #<==将a+1赋值给a,然后输出表达式的值9[root@theshu ~]# echo $((a+=1)) #<==相当于a=a+110[root@theshu ~]# echo $((a**2)) #<==计算a的平方,**表示幂运算100例4:利用
(())
双括号进行比较和判断1234567891011[root@theshu ~]# echo $((3<8)) #<==3<8的结果是成立的,因此输出了1,1表示真1[root@theshu ~]# echo $((8<3)) #<==8<3的结果是不成立的,因此输出了0,0表示假0[root@theshu ~]# echo $((8==8)) #<==判断是否相等1[root@theshu ~]# if ((8>7&&5==5)) #<==如果8>7成立并且5==5成立,则打印yes。> then> echo yes> fiyes #<==显然两个条件都成立,所以打印了yes
提示:上面设计的数字及变量必须为整数(整型),不能是小数(浮点数)或字符串。后面的bc和awk命令可以用于进行小数(浮点数)运算,但一般用到的较少。
- 例5:在变量前后使用
--
和++
特殊运算符的表达式123456789101112131415161718192021222324[root@theshu ~]# a=10[root@theshu ~]# echo $((a++))10#<==如果a在运算符(++或--)的前面,那么在输出整个表达式时,会输出a的值,因为a为10,所以表达式的值为10[root@theshu ~]# echo $a11#<==执行上面的表达式后,因为有a++,因此a会自增1,因此输出a的值为11[root@theshu ~]# a=11[root@theshu ~]# echo $((a--))11 #<==理由同上[root@theshu ~]# echo $a10[root@theshu ~]# a=10[root@theshu ~]# echo $a10[root@theshu ~]# echo $((--a))9#<==如果a在运算符(++或--)的后面,那么在输出整个表达式时,先进行自增或自减运算,因为a为10,且要自减,所以表达式的值为9[root@theshu ~]# echo $a9 #<==执行上面的表达式后,a自减1,因此a为9[root@theshu ~]# echo $((++a))10 #<==理由同上[root@theshu ~]# echo $a10
执行echo $((a++))
和$((a--))
命令输出整个表达式时,输出的值即为a的值,表达式执行完毕后,会对a进行++、–运算,而执行echo $((++a))
和echo $((--a))
命令输出整个表达式时,会先对a进行++、–的运算,然后再输出表达式的值,即为a运算后的值。
提示:有关
++
、--
运算的记忆方法:变量a在运算符之前,输出表达式的值为a,然后a自增或自减;变量a在运算符之后,输出表达式会先自增或自减,表达式的值就是自增或自减后a的值。
- 例6:通过
(())
运算后赋值给变量12345678[root@theshu ~]# myvar=99[root@theshu ~]# echo $((myvar+1)) #<=="(())"中的变量myvar前也可以加$符号,也可以不加100[root@theshu ~]# echo $(( myvar + 1 )) #<=="(())"内部内容的两端有几个空格无所谓,变量和运算符号之间有无空格也无所谓,可以有一个或多个,也可以没有100[root@theshu ~]# myvar=$((myvar+1)) #<==还可以在"(())"表达式前加$符号,将表达式赋值给变量[root@theshu ~]# echo $myvar100
提示:在
(())
中使用变量时可以去掉变量前的$
符号
- 例7:包含
(())
的各种常见运算符命令的执行示例123456789101112[root@theshu ~]# echo $((6+2)) #<==加法8[root@theshu ~]# echo $((6-2)) #<==减法4[root@theshu ~]# echo $((6*2)) #<==乘法12[root@theshu ~]# echo $((6/2)) #<==除法,取商数3[root@theshu ~]# echo $((6%2)) #<==取模,即取余数0[root@theshu ~]# echo $((6**2)) #<==幂运算36
提示:
(())
表达式在命令执行时不需要加$
符号,直接使用((6%2))
形式即可,但是如果需要输出,就要加$
符号,例如:echo $((6%2))
(())
里的所有字符之间没有空格、有一个或多个空格都不会影响结果。
- 例8:各种
(())
运算的Shell脚本示例12345678910[root@theshu ~]# cat test.sha=6b=2echo "a-b=$(($a-$b))"echo "a+b=$(($a+$b))"echo "a*b=$(($a*$b))"echo "a/b=$(($a/$b))"echo "a**b=$(($a**$b))"echo "a%b=$(($a%$b))"
脚本运行如下:
- 例9:把例8中的a、b两个变量通过命令行脚本传参,以实现混合运算脚本的功能
这是一个考察实战编程思想的综合实践考试题。
参考答案1如下:
执行结果如下:
使用脚本传参的好处是可以进行各种数字间的运算,不想前一个脚本,因为是直接定义变量的,所以只能做6和2这两个数字的运算,也就是说,使用传参,可以让脚本更具备通用性。
参考答案2如下:
这个方法虽然也可以实现同样的功能,但是对源脚本的改动过大,所以,从编程思想方面来说,不如参考答案1。
3. let运算命令的用法
- let运算命令的语法格式为:
let 赋值表达式
let赋值表达式的功能等同于
((赋值表达式))
例子:给自变量i加8
123456789[root@theshu ~][root@theshu ~][root@theshu ~]i+8[root@theshu ~][root@theshu ~][root@theshu ~][root@theshu ~]10
提示:
let i=i+8
等同于((i=i+8))
,但后者效率更高。
4. expr命令的用法
4.1. expr命令的基本用法示例
expr
(evaluate(求值)expressions(表达式))命令既可以用于整数运算,也可以用于相关字符串长度、匹配运算处理。
1. 用法1:expr用于计算
语法:expr Expression
范例:expr命令运算用法实践:
要注意,在使用expr
时:
- 运算符及用于计算的数字左右都至少有一个空格,否则会报错
- 使用称号时,必须用反斜杠屏蔽其特定含义,因为Shell可能会误解星号的含义
2. 用法2:expr配合变量计算
expr
在Shell中可配合变量进行计算,但需要用反引号将计算表达式括起来。
范例:给自变量i加6:
4.2. expr的企业级实战案例详解
1. 判断一个变量值或字符串是否为整数
在Shell编程里,由于函数库很少,所以判断字符串是否为整数就不是一键很容易的事情。在这里介绍一种简单的可以判断一个字符串是否为整数的方法。
实现原理是,利用以expr
做计算时变量或字符串必须是整数的规则,把一个变量或字符串和一个已知的整数(非0)相加,看命令返回值是否为0。若为0,则做加法的变量或字符串为整数,否则就不是整数。下面是几个示例。
示例:通过expr判断变量或字符串是否为整数
结论:利用expr做计算,将一个未知的变量和一个已知的整数相加,看返回值是否为0,如果为0就任务做加法的变量为整数,否则就不是整数。
示例:通过传参判断输出内容是否为整数
示例:通过read读入持续等待输入例子。test.sh的内容如下:
执行结果如下:
示例:将前文的混合运算小程序改成输入两个参数后进行计算的程序,并且要能判断传参的个数及通过expr判断传入的参数是否为整数。
待使用的脚本如下:
这道题的编程思路如下:
- 第一关,判断参数个数是否为2,若不是,则给出提示终止运行
- 第二关,判断传入的参数是否为整数,若不是,则给出提示终止运行
- 第三关,做运算
参考答案1:
参考答案2:
此外,用expr match功能进行整数判断时,可执行man expr
命令获取帮助。如下:
2. expr的特殊用法:判断文件扩展名是否符合要求
范例:通过expr判断文件扩展名是否符合要求
3. 通过expr计算字符串的长度
示例:利用expr计算字符串的长度
示例:编写Shell脚本,打印下面语句中字符数不大于6的单词:
更多expr的用法请查看帮助文件man expr
5. bc命令的用法
bc是Unix/Linux下的计算器,因此,除了可以作为计算器来使用,还可以作为命令行计算工具使用。
范例:将bc用在命令行下面,以实现运算功能
利用bc配合变量运算:
提示:根据bc所具有的特殊性来看,如果是小数,则选择
bc
运算没问题(但高手前辈推荐awk
);若是整数场景,可用(())
、let
、expr
等。
范例:通过一条命令计算输出1到10的表达式,并计算出结果,请使用bc命令计算。输出内容如1+2+3+4+5+6+7+8+9+10=55
这里生成上述表达式的方法有:
实现本题的多种方法如下:
只需要记住,bc
命令的独有特点是除了支持整数运算之外,还支持小数运算。
6. awk实现计算
利用awk
进行运算的效果也很好,适合小数和整数,特别是命令行计算,尤其是小数,运算很精确,好用。下面来看一个示例:
7. declare(同typeset)命令的用法
使用typeset
定义整数变量,直接进行计算。这个方法不是很常用,因为需要定义才能生效。示例如下:
8. $[] 符号的运算示例
关于$[]
符号运算的示例如下:
下面是一个打印数学杨辉三角的案例,这个案例只作为学习意义使用,对于运维工作毫无意义:
9. 基于Shell变量输入read命令的运算实践
9.1. read命令基础
Shell变量除了可以直接赋值或脚本传参外,还可以使用read
命令从标准输入中获得,read
为bash内置命令,可通过help read
查看帮助。
- 语法格式:
read [参数] [变量名]
- 常用参数如下:
-p prompt
设置提示信息-t timeout
设置输入等待时间,单位默认为秒
示例:实现read的基本读入功能:
提示:read的读入功能就相当于交互式接受用户输入,然后给变量赋值。
上面的read -p
的功能可以用echo
和read
来实现,如下:
以上两句和下面的命令相当(-t排除在外)
9.2. 使用read的常见错误
下面是一些典型使用read命令错误的地方:
read -p "Pls input:"
这里的read没有用,因为没有变量来接收用户的输入read -p "Pls input:" "$1" "$2"
这里的$1
和$2
本来是有特定功能的变量,不能用其作为变量来接受read的读入。错误在于,read后面接的是普通变量,并且将传参和read混用了,传参和read可以理解为是两种变量赋值的方法,使用其一即可。a=$1 ; read -p "Pls input:" $a
作为接收read的变量,不该带$
符号。
OK